#include "common.h"

#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common_test.h"
#include "adb/adb_device.h"
#include "util/vector.h"

// 申请一段内存,测试时用到，10个字节已经够用
#define LENGTH 10

// 初始化一个结构，不直接用于测试
static void init(struct sc_adb_device *device){
    // malloc只是申请内存，但不并初始化内容，里面仍是垃圾值
    char *text = malloc(sizeof(char)*LENGTH);
    device->model = text;
    strcpy(device->model, "model");
    assert(0 == strcmp(device->model,"model"));
    assert(NULL != device->model);

    text = malloc(sizeof(char)*LENGTH);
    device->serial = text;
    strcpy(text, "serial");

    // 下面的写法是不能赋值的
    // *device->serial = "xyz";
    
    assert(NULL != device->serial);

    text = malloc(sizeof(char)*LENGTH);
    device->state = text;
    device->state[0] = 's';
    device->state[1] = 't';
    device->state[2] = 'a';
    device->state[3] = 't';
    device->state[4] = 'e';
    device->state[5] = '\0';
    assert(NULL != device->state);

    // 这个值如果不初始化不一定是什么样的，调试时可见
    device->selected = false;
}

static void test_sc_adb_device_destroy(void){
    TEST_START_INFO;

    TEST_LINE_REPORT_START;

    // 声明完如果不进行初始化，指针没准指向什么位置，布尔值也可能是垃圾值，指针也不一定是NULL
    struct sc_adb_device device;
    init(&device);

    /* 下面的assert写法不同,效果是一样的 */
    assert(0 == strcmp(device.model,"model"));
    assert(!strcmp(device.serial,"serial"));
    assert(!strcmp(device.state,"state"));

    sc_adb_device_destroy(&device);

    // free后 指针也不一定指向到哪里，当然值也不知道会是什么垃圾值
    assert(NULL != device.model);
    assert(NULL != device.serial);
    assert(NULL != device.state);

    // 赋值为NULL以后，将不能调用strcmp函数
    // device.model = NULL;

    assert(0 != strcmp(device.model,"model"));
    assert(0 != strcmp(device.serial,"serial"));
    assert(0 != strcmp(device.state,"state"));    

    TEST_END_INFO;
}

static void test_sc_adb_device_move(void){
    /*
    C语言应该是先声明所有的变量，再开始执行语句，编译器为下面的几句话做了重排，
    执行到init方法时，dst变量已经分配了内存
    */
    struct sc_adb_device src;
    init(&src);

    struct sc_adb_device dst;
    sc_adb_device_move(&dst, &src);

    assert(0 == strcmp(dst.model,"model"));
    assert(0 == strcmp(dst.serial,"serial"));
    assert(0 == strcmp(dst.state,"state"));

    // 此处证明了先赋值NULL，再free是没有问题的
    assert(NULL == src.model);
    assert(NULL == src.serial);
    assert(NULL == src.state);

    sc_adb_device_destroy(&src);
    sc_adb_device_destroy(&dst);
}

static void test_sc_adb_devices_destroy(void){
    struct sc_vec_adb_devices vec = SC_VECTOR_INITIALIZER;
    struct sc_adb_device device;

    init(&device);
    assert(0 == strcmp(device.model,"model"));

    struct sc_adb_device device1;
    struct sc_adb_device device2;
    init(&device1);
    init(&device2);

    sc_vector_push(&vec, device);
    sc_vector_push(&vec, device1);
    sc_vector_push(&vec, device2);

    // 其实这个测试是没什么用的，因为free过的资源是无法验证的
    sc_adb_devices_destroy(&vec);

    assert(0 != strcmp(device.model,"model"));
}

static void test_sc_adb_device_get_type(void){
    char *ip_serial="192.168.1.1:1234";
    enum sc_adb_device_type ip_type = sc_adb_device_get_type(ip_serial);
    assert(SC_ADB_DEVICE_TYPE_TCPIP == ip_type);

    char *usb_serial="0a388e93";
    enum sc_adb_device_type usb_type = sc_adb_device_get_type(usb_serial);
    assert(SC_ADB_DEVICE_TYPE_USB == usb_type);

    char *emulator_serial="emulator-5556";
    enum sc_adb_device_type emulator_type = sc_adb_device_get_type(emulator_serial);
    assert(SC_ADB_DEVICE_TYPE_EMULATOR == emulator_type);
}

int main(int argc, char *argv[]) {
    (void) argc;
    (void) argv;

    test_sc_adb_device_move();
    test_sc_adb_device_destroy();
    test_sc_adb_device_get_type();
    test_sc_adb_devices_destroy();
 
    return 0;
};